﻿using Common;
using DadayunApi.Model;
using Newtonsoft.Json;
using RestSharp;
using RestSharp.Authenticators;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace DadayunApi
{
    public partial class Api
    {
        protected AppAuthBase authBase;
        protected AccessToken token;
        protected string baseUri;
        DateTime timeOfGetToken;
        /// <summary>
        /// 正在访问的资源地址，用于跟踪调试
        /// </summary>
        public string FullUri { get; protected set; }
        protected HttpStatusCode httpStatus;
        public HttpStatusCode HttpStatus { get { return httpStatus; } }
        protected string responseJson;
        protected HttpResponseHeaders responseHeader;
        public string ResponseJson { get { return responseJson; } }
        public HttpResponseHeaders ResponseHeader { get { return responseHeader; } }
        public string Token { get
            {
                if(token==null)
                {
                    token = GetToken();
                }
                if(token!=null)
                {
                    if ((DateTime.Now - timeOfGetToken).TotalMinutes > token.Expires_in)
                    {
                        token = ResfreshToken();
                        timeOfGetToken = DateTime.Now;
                    }
                    return token.Access_token;
                }
                else
                {
                    return null;
                }
                
            } }
        protected Dictionary<string, string> httpgetTokenHeader = new Dictionary<string, string>();
        public Api(AppAuthBase authBase,string baseUri)
        {
            this.authBase = authBase;
            this.baseUri = baseUri;
            httpgetTokenHeader.Add("Authorization", "Bearer " + Token);
        }
        public void SetToken(AccessToken token)
        {
            this.token = token;
            
            httpgetTokenHeader["Authorization"] = "Bearer " + Token;
        }
        public AccessToken GetToken()
        {
            AccessToken token = null;
            string uri = "connect/token";
            var client = new RestClient(baseUri);
            var request = new RestRequest(uri, Method.POST);
            request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
            client.Authenticator = new HttpBasicAuthenticator(authBase.ClientId, authBase.ClientSecret);
            request.AddParameter("client_id", authBase.ClientId);
            request.AddParameter("appSecret", authBase.ClientSecret);
            request.AddParameter("grant_type", "password");
            request.AddParameter("username", authBase.Username);
            request.AddParameter("password", authBase.Password);
            //request.AddParameter("scope", "openapi offline_access");//可不用
            IRestResponse<AccessToken> response = client.Execute<AccessToken>(request);
            if (response.IsSuccessful)
            {               
                token = response.Data;
            }
            else
            {
                responseJson = response.Content;//错误信息
            }
            return token;   
        }
        public AccessToken ResfreshToken()
        {
            string uri = "connect/token";
            var client = new RestClient(baseUri);
            var request = new RestRequest(uri, Method.POST);
            request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
            client.Authenticator = new HttpBasicAuthenticator(authBase.ClientId, authBase.ClientSecret);
            request.AddParameter("client_id", authBase.ClientId);
            request.AddParameter("appSecret", authBase.ClientSecret);
            request.AddParameter("grant_type", "refresh_token");
            request.AddParameter("refresh_token", token.Refresh_token);
            //request.AddParameter("scope", "openapi offline_access");//可不用
            IRestResponse<AccessToken> response = client.Execute<AccessToken>(request);
            if (response.IsSuccessful)
            {
                token = response.Data;
            }
            return token;
        }
        #region 基本CRUD
        public HttpStatusCode HttpGet(string uri)
        {

            FullUri = uri[0] == '/' ? baseUri + uri : baseUri + "/" + uri;
            return HttpClientHelper.HttpClientGetSync(baseUri, uri, out responseJson,out responseHeader, httpgetTokenHeader);
        }
        public HttpStatusCode HttpPost(string uri, FormUrlEncodedContent content)
        {
            FullUri = uri[0] == '/' ? baseUri + uri : baseUri + "/" + uri;
            return HttpClientHelper.HttpClientPostSync(baseUri, uri, content, out responseJson,out responseHeader, httpgetTokenHeader);
        }
        public HttpStatusCode HttpPut(string uri, FormUrlEncodedContent content)
        {
            FullUri = uri[0] == '/' ? baseUri + uri : baseUri + "/" + uri;
            return HttpClientHelper.HttpClientPutSync(baseUri, uri, content, out responseJson, out responseHeader, httpgetTokenHeader);
        }
        public HttpStatusCode HttpDelete(string uri)
        {
            FullUri = uri[0] == '/' ? baseUri + uri : baseUri + "/" + uri;
            return HttpClientHelper.HttpClientDeleteSync(baseUri, uri, out responseJson, httpgetTokenHeader);
        }
        #endregion

        
        #region 静态方法
        public static string ToISO8601Time(DateTime time)
        {
            return time.ToString("yyyy-MM-ddTHH:mm:sszzzz", DateTimeFormatInfo.InvariantInfo);
        }
        #endregion

        #region 公用方法
        /// <summary>
        /// 获取实例的总量：根据Uri获取符合Uri定义的实例总量
        /// </summary>
        /// <param name="uriWithoutLimit">不含"limit=xx"的uri</param>
        /// <returns>如果成功，返回实例总量，如果失败，返回-1</returns>
        protected int GetTotalCount(string uriWithoutLimit)
        {
            int count = -1;
            string tempUri = uriWithoutLimit + "&limit=1";
            //httpStatus = HttpClientHelper.HttpClientGetSync(baseUri, uriWithoutLimit, out responseJson, out responseHeader, httpgetTokenHeader);
            httpStatus = HttpGet(uriWithoutLimit);
            if (httpStatus == HttpStatusCode.OK)
            {
                var header = responseHeader.FirstOrDefault(h => h.Key.ToLower() == "total-count");
                count = Convert.ToInt32(header.Value.FirstOrDefault());
            }
            return count;
        }
        #endregion
    }
}
